//============================================================================
// Name        : ROMS_main.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : C++ project Part II for your class (121, or 112) 
//============================================================================
//
#include "Simple_window.h"
#include "Graph.h"
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_JPEG_Image.H>
#include <FL/Fl_RGB_Image.H>

#include "ROMS_Menu.h"

using namespace std;
using namespace ROMS;
using namespace Graph_lib;

//types we need for a ROMS GUI interface-- a memu_bar and a place to display text and a means of attaching them to a Window.

namespace Graph_lib {
//------------------------------------------------------------------------------
	struct Window_text_display : Widget {
		Window_text_display(Point XY, int W, int H, string L, Callback cb): Widget(XY, W, H, L, cb)
		{}
		void set_buffer(string s);
		void attach(Window&);
	private:
		Fl_Text_Buffer data;
		Fl_Text_Display *ptd;

	};
	void Window_text_display::attach(Window& win)
	{
		ptd = new Fl_Text_Display(loc.x, loc.y, width, height, label.c_str());
		ptd->buffer(&data);
		pw  = (Fl_Widget*) ptd;
		pw->callback(reinterpret_cast<Fl_Callback*>(do_it), &win); // pass the window
		own = &win;
	}
	void Window_text_display::set_buffer(string s) 
	{
		data.text(s.c_str());
	}

//------------------------------------------------------------------------------
	struct Menu_bar : Widget {
		Menu_bar(Point XY, int W, int H, Callback cb): Widget(XY, W, H, "", cb)
		{}
		void menu(Fl_Menu_Item *ma);
		void attach(Window&);
	private:
		Fl_Menu_Bar *pmb;
		Fl_Menu_Item *ma;

	};
	void Menu_bar::attach(Window& win)
	{
		pmb = new Fl_Menu_Bar(loc.x, loc.y, width, height);
		pmb->menu(ma);
		pw  = (Fl_Widget*) pmb; 
		pw->callback(reinterpret_cast<Fl_Callback*>(do_it), &win); // pass the window
		own = &win;
	}
	void Menu_bar::menu(Fl_Menu_Item *m) 
	{
		ma = m;
	}
}

//header declarations
void do_about_box(Graph_lib::Window&);
void do_help_box(Graph_lib::Window&); //HHC Part II B.3
void do_read(Graph_lib::Window&, ROMS_Menu&, string, string, Msg_type);
void Main_Window_CB(Fl_Widget*, void*);
void Menu_Bar_CB (Fl_Widget*, void*);
void find_menu_item_window(Graph_lib::Window&, ROMS_Menu& m); //HHC Part II C find menu item sales
void update_menu_item_window(Graph_lib::Window& w, ROMS_Menu& m); //HHC Part II C update menu item
void find_table_sales_window(Graph_lib::Window& w, ROMS_Menu& m);//TTL Part C
void update_order_item_window(Graph_lib::Window& w, ROMS_Menu& m);//TTL Part C

/*****************[THORIQ-C]***********************************/
void do_find_category_sales(Graph_lib::Window&, ROMS_Menu&);
string do_find_category_sales_button(int, ROMS_Menu&);
void do_add_recipe(Graph_lib::Window&, ROMS_Menu&);
/**************************************************************/

//Following functions for Graphing
void graph_month(Graph_lib::Window& w, ROMS_Menu& m);
void graph_table(Graph_lib::Window& w, ROMS_Menu& m);
void graph_cat_month(Graph_lib::Window& w, ROMS_Menu& m);

//global data
bool main_window_click = false;
bool menu_bar_click = false;
bool main_click_enabled = true;//used to force serialization on clicks
int window_userdata;
int menu_bar_userdata; //HHC Part II C

//main window menu bar
//Note: for expediancy sake, to define the menu bar below we used an FLTK type Fl_Menu_Item. 
//This makes our program  directly tied to FLTK instead of Dr. Stroustrup's interface Graph_lib.
//We don't like this, but we did it to save time, which often happens in the real world.
//A better solution is to write code to hide this in the implementation of the Graph_lib::Menu_bar, but that means adding
//changes to it and getting general agreement with Dr. Stroustrup. Subsequent testing and distribution would take time we don't have.
//An extra credit exercise is to see if you can eliminate direct references in your code to FLTK types like we have here
Fl_Menu_Item menu_bar[] = {
 {"Read", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Recipes", 0,  (Fl_Callback*)Main_Window_CB, Address (Read_recipes_ingredients), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Orders", 0,  (Fl_Callback*)Main_Window_CB, Address (Read_orders), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Menu Items", 0,  (Fl_Callback*)Main_Window_CB, Address (Read_category_menu_items), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Show", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Orders", 0,  (Fl_Callback*)Main_Window_CB, Address (Show_order), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Recipes", 0,  (Fl_Callback*)Main_Window_CB, Address (Show_recipe), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Menu Items", 0,  (Fl_Callback*)Main_Window_CB, Address (Show_menu), 0, FL_NORMAL_LABEL, 0, 14, 0},
 //Add Show menu items for Categories and Order Items that function like the buttons for Categories and Order Items in the main window.
 {"Categories", 0,  (Fl_Callback*)Main_Window_CB, Address (Categories_button), 0, FL_NORMAL_LABEL, 0, 14, 0}, //HHC Part II B.3
 {"Order Items", 0,  (Fl_Callback*)Main_Window_CB, Address (Recipes_button), 0, FL_NORMAL_LABEL, 0, 14, 0}, //HHC Part II B.3
 {0,0,0,0,0,0,0,0,0},
 {"Find", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Category Sales", 0,  (Fl_Callback*)Main_Window_CB, Address (Find_category_sales), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Table Sales", 0,  (Fl_Callback*)Main_Window_CB, Address (Find_table_sales), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Menu Item Sales", 0,  (Fl_Callback*)Main_Window_CB, Address (Find_menu_item_sales), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Update", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Add Order Item", 0,  (Fl_Callback*)Main_Window_CB, Address (Update_add_order_item), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Add Menu Item", 0,  (Fl_Callback*)Main_Window_CB, Address (Update_add_menu_item), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Add Recipe", 0,  (Fl_Callback*)Main_Window_CB, Address (Update_add_recipe), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Graph",0,0,0,64, FL_NORMAL_LABEL, 0,14,0},
 {"Order Sales by Month", 0,(Fl_Callback*)Main_Window_CB, Address (Graph_month_button), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Sales by Table", 0,(Fl_Callback*)Main_Window_CB, Address (Graph_table_button), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Category Sales by Month", 0,(Fl_Callback*)Main_Window_CB, Address (Graph_cat_month_button), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"About", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Info", 0,  (Fl_Callback*)Main_Window_CB, Address (About_info), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Help", 0,  (Fl_Callback*)Main_Window_CB, Address (About_help), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Exit", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Save and exit", 0,  (Fl_Callback*)Main_Window_CB, Address (Exit_program), 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {0,0,0,0,0,0,0,0,0}
};


//call back functions
void recps_cb(Address addr, Address) // callback for recipes button
{
	Main_Window_CB((Fl_Widget*) addr, Address (Tables_button));
}
void order_cb(Address addr, Address) // callback for orders button
{
	Main_Window_CB((Fl_Widget*) addr, Address (Orders_button));
}
void cat_cb(Address addr, Address) // callback for category button
{
	Main_Window_CB((Fl_Widget*) addr, Address (Categories_button));
}
void mi_cb(Address addr, Address) // callback for menu item button
{
	Main_Window_CB((Fl_Widget*) addr, Address (Menu_items_button));
}
void oi_cb(Address addr, Address) // callback for order item button
{
	Main_Window_CB((Fl_Widget*) addr, Address (Recipes_button));
}
 void display_cb(Address addr, Address) // callback for display window
{
	Main_Window_CB((Fl_Widget*) addr, Address (Display_window));
}
 void menu_bar_cb(Address addr, Address)//callback for menu bar
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address (Menu_bar_cb));
 }

 void find_menu_item_cb(Address addr, Address)//callback for Find Menu Item Sales
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address (Find_menu_item_sales));
 }

 void update_menu_item_cb(Address addr, Address)//callback for Update Button in Update MEnu Item Window
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address(Update_add_menu_item));
 } //HHC Part II C
 
 /****************[THORIQ-C]******************************/
void find_category_sales_cb(Address addr, Address) // callback for find category sales button
{
	Main_Window_CB((Fl_Widget*) addr, Address (Find_category_sales_button));
}

void add_recipe_cb(Address addr, Address) // callback for find category sales button
{
	Main_Window_CB((Fl_Widget*) addr, Address (Add_recipe_button));
}
/*******************************************************/

void find_table_sales_cb(Address addr, Address) // callback for find table sales button //TTL PartC
{
	Main_Window_CB((Fl_Widget*) addr, Address (Find_table_sales_button));
}

 void update_order_item_cb(Address addr, Address)//callback for Update Button in Update Order Item Window//TTL PartC
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address(Update_add_order_item));
 }
 
 //Following methods are for Graph buttons//TTL PartD
 
 void graph_cb(Address addr, Address)//callback for Graph Button (just opens dropdown menu) //TTL PartD1
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address(Graph_button));
 }
 
  void graph_month_cb(Address addr, Address)//callback for Graph Order Sales by Month button//TTL PartD1
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address(Graph_month_button));
 }
 
  void graph_table_cb(Address addr, Address)//callback for Graph Sales by Table button//TTL PartD2
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address(Graph_month_button));
 }
 
  void graph_cat_month_cb(Address addr, Address)//callback for Graph Category Sales by Month//TTL PartD3
 {
	 Menu_Bar_CB((Fl_Widget*) addr, Address(Graph_cat_month_button));
 }

void Menu_Bar_CB (Fl_Widget*, void* ud) {
	cout << "Menu Bar Callback" << " Userdata=" << (int) ud << "\n";
	menu_bar_click = true;
	menu_bar_userdata = (int) ud; //HHC Part II C
}

void Main_Window_CB(Fl_Widget*, void* ud) {
	if(main_click_enabled)//don't signal the window click if main loop is active
	{
		cout << "Main Window Callback" << " Userdata=" << (int) ud << "\n";
		window_userdata = (int) ud;
		main_window_click = true;
		main_click_enabled = false; //main loop active on current click
	}
}
//wait functions for callbacks to be executed
void wait_for_main_window_click() {
	while (!main_window_click) 
		Fl::wait();
	main_window_click = false;
	Fl::redraw();
}

void wait_for_menu_bar_click() {
	while (!menu_bar_click)
		Fl::wait();
	menu_bar_click = false;
	Fl::redraw();
}

int main()
{
	//create the main window and display it
	ROMS_Menu m;
    Graph_lib::Window sw(600, 500, "Restaurant Order Management System");
    Button recps(Point(40, 50), 100, 30, "Recipes", recps_cb);
	sw.attach(recps);
	Button order(Point(40, 100), 100, 30, "Orders", order_cb);
	sw.attach(order);
	Button cat(Point(40, 150), 100, 30, "Categories", cat_cb);
	sw.attach(cat);
	Button mi(Point(40, 200), 100, 30, "Menu Items", mi_cb);
	sw.attach(mi);
	Button ci(Point(40, 250), 100, 30, "Order Items", oi_cb);
	sw.attach(ci);
    sw.callback((Fl_Callback*)Main_Window_CB, Address (Exit_program));
	Menu_bar mb(Point(0, 0), 600, 30, menu_bar_cb);
    mb.menu(menu_bar);
	sw.attach(mb);

	Window_text_display t(Point(150,50),400, 400, "Data Display", display_cb );
	t.set_buffer("No Data Loaded\n");
	sw.attach(t);
 	sw.resizable(&sw);
	

	//main loop to execute user clicks on the main window
	//do you understand how this loop works compared to the way the main loop worked in Part I of the project?
	try {
		
		while(true) {
			main_click_enabled = true;
			wait_for_main_window_click();
			cout << "Act on userdata = " << window_userdata << endl;
			switch(window_userdata) 
			{
				//need to complete all the menu cases
				case Read_recipes_ingredients:
					do_read(sw, m, "recipes.dat", "Open Recipes/Ingredients File", Read_recipes_ingredients);
					break;
				case Read_orders:
					do_read(sw, m, "orders.dat", "Open Order/Order Items File", Read_orders);
					break;
				case Read_category_menu_items:
					do_read(sw, m, "catmenu.dat", "Open Category/Menu Item File", Read_category_menu_items);
					break;
				/*THORIQ-B.2*************************/
				//Show menu selections
				case Show_order: case Show_recipe: case Show_menu:
					t.set_buffer((m.show_menu((Msg_type) window_userdata).c_str()));
					break;
				/*************************************/
				/* THORIQ-C***************************/
				case Find_category_sales:
					do_find_category_sales(sw, m);
					break;
				case Update_add_recipe:
					do_add_recipe(sw, m);
					break;
				/************************************/
				case About_info:
					do_about_box(sw);
					break;
				/* Show help, HHC Part II B.3 */
				case About_help:
					do_help_box(sw);//create a Help window
					break;
				/******************************/
				case Tables_button: case Orders_button: case Categories_button: case Recipes_button: case Menu_items_button:
					//[THORIQ-B.2] added function to make it fixed-width
					t.set_buffer(m.show_button((Msg_type) window_userdata).c_str());
					break;
				/** Find Menu Item Sales, HHC Part II C-find menu item **/
				case Find_menu_item_sales:
					find_menu_item_window(sw, m);// Show popup Find Menu Items Sales Window
					break;
				/********************************************************/
				/** Update Menu Item Sales, HHC Part II C-update menu item **/
				case Update_add_menu_item:
					update_menu_item_window(sw, m);// Show popup Find Menu Items Sales Window
					break;
				/********************************************************/
				case Find_table_sales: //TTL Part C
					find_table_sales_window(sw,m); //TTL Part C
					break;
				case Update_add_order_item:	//TTL Part C
					update_order_item_window(sw,m);	//TTL Part C
					break;
				case Graph_month_button:
					graph_month(sw,m);
					break;
				case Graph_table_button:
					graph_table(sw,m);
					break;
				case Graph_cat_month_button:
					graph_cat_month(sw,m);
					break;
				case Exit_program:
					cout << "save files and exit\n";
					m.ROMS_Menu::save();
					exit(0); //exit program
					break;
				default:
					cout << "case not implemented\n";
			}
		}
		return 0;
	}
	catch(exception& e) {
		cerr << "exception: " << e.what() << '\n';
		return 1;
	}
	catch (...) {
		cerr << "Some exception\n";
		return 2;
	}
}

//show about box info window
//The following function was edited by Travis Lamb for Part B.1
//TTL B.1
void do_about_box(Graph_lib::Window& w) 
{
	Graph_lib::Window ab(Point(w.x()+100, w.y()+100), 800, 600, "About");
	ab.color(Color::white);
	ab.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));
	Text msg1(Point(5,15), "Ward Project Part II: Restaurant Order Management System");
	Text msg2(Point(55,30), "Team 11 Members:");
	
	Text msg3(Point(260,75), "Hendra Hadhil Choiri");
	Text msg4(Point(260,90), "Fourth Year");
	Text msg5(Point(260,105), "ITB");
	
	Text msg6(Point(605,75), "Ahmad Thoriq");
	Text msg7(Point(605,90), "Fourth Year");
	Text msg8(Point(605,105), "ITB");
	
	Text msg9(Point(260,340), "Travis Lamb");
	Text msg10(Point(260,355), "Freshman");
	Text msg11(Point(260,370), "TAMU");
	
	Image img1(Point(55,60),"hendracrop.jpg");
	Image img2(Point(400,60),"thoriqcrop.jpg");
	Image img3(Point(55,325),"traviscrop.jpg");
	
	//fl_draw_image((uchar*)"traviscrop.jpg", 255, 60, 200, 25, 3, 0);
	//Fl_JPEG_Image img1 = new Fl_JPEG_Image("traviscrop.jpg");
	msg1.set_color(Color::blue);
	msg2.set_color(Color::black);
	msg3.set_color(Color::black);
	msg4.set_color(Color::black);
	msg5.set_color(Color::black);
	msg6.set_color(Color::black);
	msg7.set_color(Color::black);
	msg8.set_color(Color::black);
	msg9.set_color(Color::black);
	msg10.set_color(Color::black);
	msg11.set_color(Color::black);
	ab.attach(msg1);
	ab.attach(msg2);
	ab.attach(msg3);
	ab.attach(msg4);
	ab.attach(msg5);
	ab.attach(msg6);
	ab.attach(msg7);
	ab.attach(msg8);
	ab.attach(msg9);
	ab.attach(msg10);
	ab.attach(msg11);
	ab.attach(img1);
	ab.attach(img2);
	ab.attach(img3);
	//ab.attach(img1);
	//img1.draw();
	wait_for_menu_bar_click();
	
	//clean up window
	ab.detach(msg1);
	ab.detach(msg2);
	ab.detach(msg3);
	//ab.detach(img1);
	return;
}

//show Help box window
void do_help_box(Graph_lib::Window& w) 
{
	Graph_lib::Window help(Point(w.x()+100, w.y()+100), 650, 120, "Find Menu Item Sales");
	help.color(Color::white);
	help.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));
	Text HTitle(Point(15,20), "How to use this ROM System:");
	HTitle.set_font_size(16);
	HTitle.set_color(Color::blue);
	Text H1(Point(15,40), "1. Read data files (Recipes, Orders, Menu Items) from Read menu and browse the file location");
	Text H2(Point(15,55), "2. Show The contents of data by clicking one of 5 buttons or in Show menu");
	Text H3(Point(15,70), "3. Find Category/Table/Menu Item sales information in Find menu");
	Text H4(Point(15,85), "4. Update some data from Update menu");
	Text H5(Point(15,100), "5. About menu contains developer's info and ROMS Help");
	Text H6(Point(15,115), "6. Click Exit then Save and exit to close this program ");

	H1.set_color(Color::black);
	H2.set_color(Color::black);
	H3.set_color(Color::black);
	H4.set_color(Color::black);
	H5.set_color(Color::black);
	H6.set_color(Color::black);
	
	help.attach(HTitle);
	help.attach(H1);
	help.attach(H2);
	help.attach(H3);
	help.attach(H4);
	help.attach(H5);
	help.attach(H6);
	wait_for_menu_bar_click();
	help.detach(HTitle);//clean up window
	return;

}

void do_read(Graph_lib::Window& w, ROMS_Menu& m, string dfn, string msg, Msg_type type)
{
	//Here again we linked our code directly to the FLTK library instead of creating an interface in our Graph_lib interface to FLTK
	//We did it for lack of time, which reflects the real word. Unfortunately if we wanted to move our code to a different graphics
	//library, we have to change our code and not just our Graphic_lib implementation. we are using the FLTK file chooser directly.
	Fl_File_Chooser fc(dfn.c_str(), "*.dat", Fl_File_Chooser::CREATE, msg.c_str());
	fc.show();
	while (fc.shown())
		Fl::wait();	//wait for OK or Cancel button
	if(0!=fc.value())//make sure there is a string to use as a filename
	{
		string fname = fc.value();
		switch(type) {
			case Read_recipes_ingredients:
				m.read_recipes_ingredients(fname);
				break;
			case Read_orders:
				m.Read_orders(fname);
				break;
			case Read_category_menu_items:
				m.read_catprds(fname);
				break;
			default:
				throw InvalidType();
		}
	}
	return;
}

//Functions and GUI for Find Menu Item Sales, HHC Part II C
void find_menu_item_window(Graph_lib::Window& w, ROMS_Menu& m) 
{
	Graph_lib::Window F(Point(w.x()+100, w.y()+100), 400, 100, "Find Menu Item Sales");
	F.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));

	vector<Menu_Item> menu_items = m.get_menu_items();
	if(menu_items.size()>0){
		Fl_Choice menuitem_choices(170,20,150,20,"Find sales for Menu Item: ");
		for(int i=0; i<menu_items.size(); ++i)
			menuitem_choices.add(menu_items[i].get_name().c_str());
		menuitem_choices.callback((Fl_Callback*)Menu_Bar_CB, Address(Find_menu_item_sales));
		F.add(menuitem_choices);

		Text Status(Point(20,60),"");
		Status.set_color(Color::blue);
		Status.set_font_size(15);
		F.attach(Status);
		bool find=true;
		while(find){
			wait_for_menu_bar_click();
			if(menu_bar_userdata==Find_menu_item_sales)
				Status.set_label(m.findSalesByMenuItemID(menu_items[menuitem_choices.value()].get_menu_item_id()));
			else find=false;
		}
	}
	else{
		Text Message1(Point(20,30),"Error: Menu Items Data is Empty..");
		Text Message2(Point(20,60),"Make sure you have read the data!!");
		Message1.set_font_size(16);
		Message1.set_color(Color::red);
		Message2.set_color(Color::red);
		F.attach(Message1);
		F.attach(Message2);
		wait_for_menu_bar_click();
	}
	return;
}//HHC Part II C

//Functions and GUI for Find Menu Item Sales, HHC Part II C
void update_menu_item_window(Graph_lib::Window& w, ROMS_Menu& m) 
{
	Graph_lib::Window F(Point(w.x()+100, w.y()+100), 500, 300, "Update/Add Menu Item");
	F.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));

	vector<Menu_Item> menu_items = m.get_menu_items();

	Text title(Point(50,20), "Update/Add A Menu Item");
	title.set_font_size(16);
	F.attach(title);

	In_box MI_ID(Point(150,50),40,20,"Menu Item ID    : ");
	In_box Cat_ID(Point(150,75),40,20,"Category ID     : ");
	In_box Rec_ID(Point(150,100),40,20,"Recipe ID       : ");
	In_box MI_Name(Point(150,125),100,20,"Menu Item Name  : ");
	In_box MI_Price(Point(150,150),40,20,"Menu Item Price : ");
	In_box Desc(Point(150,175),300,20,"Description     : ");
	F.attach(MI_ID);
	F.attach(Cat_ID);
	F.attach(Rec_ID);
	F.attach(MI_Name);
	F.attach(MI_Price);
	F.attach(Desc);
	
	Button Update_btn(Point(30,210),80,30,"UPDATE",update_menu_item_cb);
	F.attach(Update_btn);

	Text Status(Point(20,270),"");
	Status.set_color(Color::blue);
	Status.set_font_size(15);
	F.attach(Status);

	bool updt=true;
	while(updt){
		wait_for_menu_bar_click();
		if(menu_bar_userdata==Update_add_menu_item){
			if(m.updateMenuItem(MI_ID.get_int(), Cat_ID.get_int(), Rec_ID.get_int(), MI_Name.get_string(), strtod(MI_Price.get_string().c_str(),NULL), Desc.get_string()))
				Status.set_label(MI_Name.get_string()+" Menu Item Has Been Edited");
			else
				Status.set_label(MI_Name.get_string()+" Has Been Added to Menu Items Data");
		}
		else updt=false;
	}
	return;
}//HHC Part II C

//[THORIQ-C]
//show window for find category sales function
void do_find_category_sales(Graph_lib::Window& w, ROMS_Menu& m) 
{
	Graph_lib::Window win(Point(w.x()+100, w.y()+100), 300, 170, "Find Category Sales");
	win.callback((Fl_Callback*)Main_Window_CB, Address (Close_find_category_sales));

	Text title(Point(15,30), "Find Category Sales");
	title.set_font_size(16);
	title.set_color(Color::black);
	In_box cat_id(Point(100, 50), 50, 20, "Category ID: ");

	Text res(Point(15, 125), "");
	res.set_color(Color::black);
	Button find_button(Point(15, 80), 50, 20, "Find", find_category_sales_cb);

	win.attach(title);
	win.attach(cat_id);
	win.attach(res);
	win.attach(find_button);

	try 
	{
		while(true)
		{
			main_click_enabled = true;
			wait_for_main_window_click();
			cout << "Act on userdata = " << window_userdata << endl;
			switch(window_userdata) 
			{
				case Find_category_sales_button:
					int val;
					if((val = cat_id.get_int()) == -999999) 
					{
						res.set_label("Please type the category ID you want to find");
					}
					else
					{
						res.set_label(do_find_category_sales_button(val, m));
					}
					break;
				case Close_find_category_sales:
					cout << "exit";
					return;
					break;
				default: cout << "case not implemented\n";
			}
		}
	}
	catch(exception& e)	{cerr << "exception: " << e.what() << '\n';return;}
	catch(...)			{cerr << "Some exception\n";return;}
	return;
}

//[THORIQ-C]
//obtain total sales for the specified cat_id
string do_find_category_sales_button(int cat_id, ROMS_Menu& m){
	stringstream ss;
	if(m.is_category_available(cat_id))
	{
		ss << '$' << m.get_category_sales(cat_id);
	}
	else
	{
		ss << "Category with ID #" << cat_id << " doesn't exist";
	}
	return ss.str();
}

//[THORIQ-C]
//show window for add recipe function
void do_add_recipe(Graph_lib::Window& w, ROMS_Menu& m)
{
	
	
	Graph_lib::Window win(Point(w.x()+100, w.y()+100), 400, 300, "Add Recipe");
	win.callback((Fl_Callback*)Main_Window_CB, Address (Close_add_recipe));

	Text title(Point(172,30), "Add Recipe");
	title.set_color(Color::black);
	title.set_font_size(16);
	In_box recipe_id(Point(95, 40), 50, 20, "Recipe ID: ");
	In_box chef(Point(95, 70), 150, 20, "Chef Name: ");
	In_box inst(Point(95, 100), 250, 100, "Instructions: ");

	Text res(Point(15, 270), "");
	res.set_color(Color::black);
	Button add_button(Point(15, 220), 150, 20, "Add new recipe", add_recipe_cb);

	win.attach(title);
	win.attach(recipe_id);
	win.attach(chef);
	win.attach(inst);
	win.attach(res);
	win.attach(add_button);
	
	
	try {
		while(true) {
			main_click_enabled = true;
			wait_for_main_window_click();
			cout << "Act on userdata = " << window_userdata << endl;
			switch(window_userdata) 
			{
				case Add_recipe_button:
					res.set_label(m.add_recipe(recipe_id.get_int(), chef.get_string(), inst.get_string()));
					break;
				case Close_add_recipe:
					cout << "exit";
					return;
					break;
				default: cout << "case not implemented\n";
			}
		}
	}
	catch(exception& e)	{cerr << "exception: " << e.what() << '\n';return;}
	catch(...)			{cerr << "Some exception\n";return;}
	return;
}

//Functions and GUI for Find Table Sales TTL Part C
void find_table_sales_window(Graph_lib::Window& w, ROMS_Menu& m) 
{
	vector<Menu_Item> menu_items = m.get_menu_items();
	vector<Order> orders = m.get_orders();
	vector<Order_Item> order_items = m.get_order_items();
	
	Graph_lib::Window win(Point(w.x()+100, w.y()+100), 300, 170, "Find Table Sales");
	win.callback((Fl_Callback*)Main_Window_CB, Address (Close_find_table_sales));

	Text title(Point(15,30), "Find Table Sales");
	title.set_font_size(16);
	title.set_color(Color::black);
	In_box table_id(Point(100, 50), 50, 20, "Table ID: ");

	Text res(Point(15, 125), "Be sure to read data.");
	res.set_color(Color::black);
	Button find_button(Point(15, 80), 50, 20, "Find", find_table_sales_cb);

	win.attach(title);
	win.attach(table_id);
	win.attach(res);
	win.attach(find_button);
	
	try 
	{
		while(true)
		{
			main_click_enabled = true;
			wait_for_main_window_click();
			cout << "Act on userdata = " << window_userdata << endl;
			switch(window_userdata) 
			{
				case Find_table_sales_button:
					int val;
					if((val = table_id.get_int()) == -999999) 
					{
						res.set_label("Please type the Table ID you want to find");
					}
					else
					{
						if(menu_items.size() > 0 && orders.size() > 0 && order_items.size() > 0)
						{
							double total = 0;
							int tblid = table_id.get_int();
							int ordrid = 0;
							int i =0;
							bool found = false;
							while(i<orders.size() && !found)
							{
								if(orders[i].Order::get_table_id() == tblid)
								{
									ordrid = orders[i].Order::get_order_id();
									found = true;
								}
								
								i++;
							}
	
							if(found)
							{
								found = false;
								i=0;
								while(i<order_items.size())
								{
									if(order_items[i].Order_Item::get_order_id() == ordrid)
									{
										int menuitemid = order_items[i].Order_Item::get_menu_item_id();
										int j =0;
										
										found = false;
										while(j<menu_items.size() && !found)
										{
											if(menu_items[j].Menu_Item::get_menu_item_id() == menuitemid)
											{
												total += (menu_items[j].Menu_Item::get_price())*(order_items[i].Order_Item::get_qty());
												
												found = true;
											}
											
											j++;
										}
	
									}
									i++;
								}
	
								
								ostringstream oss;
							
								oss << "Total sales for Table ID #" << tblid << " is $" << total;
								
								res.set_label(oss.str());
							}
							else
							{
								res.set_label("No such ID is found");
							}
						}
						else
						{
							res.set_label("Be sure to read the data files.");
						}
					}
					break;
				case Close_find_table_sales:
					cout << "exit";
					return;
					break;
				default: cout << "case not implemented\n";
			}
		}
	}
	catch(exception& e)	{cerr << "exception: " << e.what() << '\n';return;}
	catch(...)			{cerr << "Some exception\n";return;}
	return;
}//TTL Part C

//Functions and GUI for update order item, TTL Part C
void update_order_item_window(Graph_lib::Window& w, ROMS_Menu& m) 
{
	Graph_lib::Window win(Point(w.x()+100, w.y()+100), 500, 300, "Update/Add Order Item");
	win.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));

	vector<Order_Item> order_items = m.get_order_items();

	Text title(Point(50,20), "Update/Add An Order Item");
	title.set_color(Color::blue);
	title.set_font_size(16);
	win.attach(title);

	In_box seat_idb(Point(150,50),40,20,"Seat ID: ");
	In_box order_idb(Point(150,75),40,20,"Order ID: ");
	In_box menu_item_idb(Point(150,100),40,20,"Menu Item ID: ");
	In_box qtyb(Point(150,125),30,20,"Quantity Ordered: ");
	win.attach(seat_idb);
	win.attach(order_idb);
	win.attach(menu_item_idb);
	win.attach(qtyb);
	
	Button Update_btn(Point(30,210),80,30,"UPDATE",update_order_item_cb);
	win.attach(Update_btn);

	Text Status(Point(20,270),"");
	Status.set_color(Color::blue);
	Status.set_font_size(15);
	win.attach(Status);

	bool updt=true;
	while(updt){
		wait_for_menu_bar_click();
		if(menu_bar_userdata==Update_add_order_item){
			m.updateOrderItem(seat_idb.get_string(),order_idb.get_int(),menu_item_idb.get_int(),qtyb.get_int());
			Status.set_label("Order Item has been added to Order Items Data");
		}
		else updt=false;
	}
	return;
}//TTL Part C

void graph_month(Graph_lib::Window& w, ROMS_Menu& m)
//graph the total of all order sales by month, HHC Part II D.1
{
	Graph_lib::Window win(Point(w.x()+100, w.y()+100), 600, 600, "Graph Order Sales by Month");
	//win.color(Color::white);
	win.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));
	Text title(Point(200,30), "Graph of Order Sales by Month");
	title.set_color(Color::blue);
	title.set_font_size(16);
	win.attach(title);
	
	//create axises
	Axis xa(Axis::x, Point(60,500), 480, 12, "");
	Axis ya(Axis::y, Point(60,500), 400, 20, "Total Sales");
	win.attach(xa);
	win.attach(ya);
	Text xname(Point(300,550),"Month");
	win.attach(xname);

	//create labels for x-axis
	int pos = 90; int dist = 40; //position and distance of each label
	int bottompos = 520;

	string monthnames[12]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
	Vector_ref<Text> XLabel;
	for(int i=0; i<12; ++i){
		XLabel.push_back(new Text(Point(pos,bottompos),monthnames[i]));
		win.attach(XLabel[i]);
		pos+=dist;
	}

	//create labels for y-axis
	pos = 505; dist = 20; //position and distance of each label
	int leftpos = 30;

	Vector_ref<Text> YLabel;
	for(int i=0; i<=20; ++i){
		ostringstream oss;
		oss<<20*i;
		YLabel.push_back(new Text(Point(leftpos,pos),oss.str()));
		win.attach(YLabel[i]);
		pos-=dist;
	}

	//drawing the graph
	map<int,double> sales= m.get_sales_per_month(); //sales of each month, 1=jan, 12=dec
	Open_polyline fsales;
	int xpos = 100, xdist = 40, ypos;
	cout<< "Sales per month: ";//debug
	for(int month=1; month<=12; ++month){
		ypos = 500-(sales[month]);
		fsales.add(Point(xpos,ypos));
		xpos+=xdist;
		cout<< sales[month]<<" ";//debug
	}
	cout<<endl;//debug
	fsales.set_color(Color::dark_green);
	win.attach(fsales);
	wait_for_menu_bar_click();
	
	return;
}//HHC Part II D.1

void graph_table(Graph_lib::Window& w, ROMS_Menu& m)
{
	vector<Menu_Item> menu_items = m.get_menu_items();
	vector<Order> orders = m.get_orders();
	vector<Order_Item> order_items = m.get_order_items();

	Graph_lib::Window win(Point(w.x()+100, w.y()+100), 1000, 600, "Graph Total Sales by Table");
	//win.color(Color::white);
	win.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));
	Text title(Point(200,30), "Graph of Total Sales by Table");
	title.set_color(Color::black);
	win.attach(title);
	
	if(menu_items.size() > 0 && orders.size() > 0 && order_items.size() > 0)
	{
		//create axises
		Axis xa(Axis::x, Point(60,500), 880, 1, "");
		Axis ya(Axis::y, Point(60,500), 400, 25, "Total Sales");
		win.attach(xa);
		win.attach(ya);
		Text xname(Point(300,550),"Table ID");
		win.attach(xname);
		
		//creating labels for x axis
		int pos = 60;
		int dist = 820/orders.size();
		int bottpos=510;
		Vector_ref<Text> xlabel;
		for(int i = 0; i < orders.size(); i++)
		{
			ostringstream oss;
			oss << orders[i].get_table_id();
			
			xlabel.push_back(new Text(Point(pos,bottpos+((i%2)*10)),oss.str()));
			xlabel[i].set_font_size(8);
			win.attach(xlabel[i]);
			pos+=dist;
		}
		
		//create labels for y-axis *****PLACEHOLDER*****
		pos = 505; dist = 16; //position and distance of each label
		int leftpos = 30;

		Vector_ref<Text> YLabel;
		for(int i=0; i<=25; ++i){
			ostringstream oss;
			oss<<2.0*i;
			YLabel.push_back(new Text(Point(leftpos,pos),oss.str()));
			win.attach(YLabel[i]);
			pos-=dist;
		}
		
		//display data
		pos = 60;
		dist = 820/orders.size();
		bottpos=500;
		Vector_ref<Rectangle> rect;
		for(int i = 0; i < orders.size(); i++)
		{
			double total = 0.0;
			int order_id = orders[i].get_order_id();
			
			for(int j = 0; j< order_items.size(); j++)
			{
				if(order_id == order_items[j].get_order_id())
				{
					int menu_item_id = order_items[j].get_menu_item_id();
					for(int k = 0; k < menu_items.size();k++)
					{
						if(menu_item_id == menu_items[k].get_menu_item_id())
						{
							total += menu_items[k].get_price() * order_items[j].get_qty();
							k=menu_items.size();
						}
					}
				}
			}
			
			//cout << total<<" | ";
			int height = (int)(total*8);
			if(height==0)
				height = 1;
			//cout << total<<endl;
			rect.push_back(new Rectangle(Point(pos+i*dist,bottpos-height),dist,height));
			rect[i].set_fill_color(Color::blue);
			win.attach(rect[i]);
		}
		
		wait_for_menu_bar_click();
	}
	else
	{
		Text warning(Point(200,50),"Data must be read before the table can be displayed.");
		win.attach(warning);
		
		wait_for_menu_bar_click();
	}
	
	return;
}

/**********************[THORIQ-D]*******************************/
//draw the bars for each category per month
void draw_bars_for_cat_month(map<int,double>& cat_sales, Vector_ref<Open_polyline>& bar_vec, Vector_ref<Text>& tex_vec, ROMS_Menu& m, int bar_pos) {
	//initialize bar maximum height, offset, and height of the current bar
	int bar_height = 400, y_offset = 500, height = 0;

	vector<Category> cat_list = m.get_category_list();
	for(int i = 0; i < cat_list.size(); ++i) {
		double percentage = cat_sales[cat_list.at(i).get_cat_id()];
		if(percentage != 0) {
			y_offset -= height;
			height = bar_height * percentage;
			bar_vec.push_back(new Open_polyline());
			bar_vec[bar_vec.size()-1].add(Point(bar_pos,y_offset));
			bar_vec[bar_vec.size()-1].add(Point(bar_pos,y_offset-height));
			bar_vec[bar_vec.size()-1].add(Point(bar_pos+50,y_offset-height));
			bar_vec[bar_vec.size()-1].add(Point(bar_pos+50,y_offset));
			bar_vec[bar_vec.size()-1].set_fill_color(i+1);
			bar_vec[bar_vec.size()-1].set_color(i+1);
			//draw the percentage text
			stringstream ss;
			ss << (int)(percentage*100) << "%";
			tex_vec.push_back(new Text(Point(bar_pos+15,y_offset-(height/2)),ss.str()));
		}
	}
}

//draw legends
void draw_legends_for_cat_month(Vector_ref<Text>& text_vec, Vector_ref<Graph_lib::Rectangle>& rec_vec, ROMS_Menu& m) {
	vector<Category> cat_list = m.get_category_list();
	for(int i = 0; i < cat_list.size(); ++i) {
		text_vec.push_back(new Text(Point(795,200+(i*15)),cat_list.at(i).get_cat_name()));
		rec_vec.push_back(new Graph_lib::Rectangle(Point(870, 190+(i*15)), 10, 10));
		rec_vec[i].set_fill_color(i+1);
		rec_vec[i].set_color(i+1);
	}
}

//create graphs that represent the sales percentage of each category per month
void graph_cat_month(Graph_lib::Window& w, ROMS_Menu& m)
{
	Graph_lib::Window win(Point(w.x()+100, w.y()+100), 900, 600, "Graph Category Sales by Month");
	//win.color(Color::white);
	win.callback((Fl_Callback*)Menu_Bar_CB, Address (Close_about_box));
	Text title(Point(270,30), "Graph of Category Sales by Month");	
	title.set_color(Color::black);
	title.set_font_size(20);	
	win.attach(title);

	//create axises
	Axis xa(Axis::x, Point(45,500), 720, 0, "");
	Axis ya(Axis::y, Point(45,500), 400, 10, "Sales Percentage");
	Text xname(Point(400,550),"Month");
	xname.set_font_size(16);
	win.attach(xname);

	//create labels for x-axis
	int pos = 70; int dist = 60; //position and distance of each label
	int bottompos = 520;
	string monthnames[12]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
	Vector_ref<Text> XLabel;
	for(int i=0; i<12; ++i){
		XLabel.push_back(new Text(Point(pos,bottompos),monthnames[i]));
		win.attach(XLabel[i]);
		pos+=dist;
	}

	//create labels for y-axis
	pos = 505; dist = 40; //position and distance of each label
	int leftpos = 20;

	Vector_ref<Text> YLabel;
	for(int i=0; i<=10; ++i){
		ostringstream oss;
		oss<<10*i;
		YLabel.push_back(new Text(Point(leftpos,pos),oss.str()));
		win.attach(YLabel[i]);
		pos-=dist;
	}

	//ref vector for legends
	Vector_ref<Text> cat_legend_t;
	Vector_ref<Graph_lib::Rectangle> cat_legend_r;
	//draw legends
	draw_legends_for_cat_month(cat_legend_t, cat_legend_r, m);
	for(int i = 0; i < cat_legend_t.size(); ++i) {
		win.attach(cat_legend_t[i]);
		win.attach(cat_legend_r[i]);
	}

	//calculate percentage category sales per month
	map<int,map<int,double> > cat_per_month = m.get_category_percentage();
	
	Vector_ref<Open_polyline> cat_bar;
	Vector_ref<Text> cat_perc;
	//draw bars
	for(int mon = 1; mon <= 12; ++mon) {
		draw_bars_for_cat_month(cat_per_month[mon], cat_bar, cat_perc, m, 55+(mon-1)*60);
	}

	for(int i = 0; i < cat_bar.size(); ++i) {
		win.attach(cat_bar[i]);
	}
	for(int i = 0; i < cat_perc.size(); ++i) { //attached separately from the bars to make them displayed on top
		win.attach(cat_perc[i]);
	}

	win.attach(xa);
	win.attach(ya);
	
	wait_for_menu_bar_click();
	
	return;
}
/*******************[THORIQ-D]**************************/